<template>
  <div class="rate">
    <span
      v-for="item in field.max"
      class="rate__item"
      @mousemove="setCurrentValue(item, $event)"
      @mouseleave="resetCurrentValue"
      @click="selectValue(item)"
      :style="{ cursor: field.disabled ? 'auto' : 'pointer' }">
      <i
        :class="[classes[item - 1], { 'hover': hoverIndex === item }]"
        class="rate__icon"
        :style="getIconStyle(item)">
        <i
          v-if="showDecimalIcon(item)"
          :class="decimalIconClass"
          :style="decimalStyle"
          class="rate__decimal">
        </i>
      </i>
    </span>
    <span v-if="field.showText" class="rate__text" :style="{ color: field.textColor }">{{ text }}</span>
  </div>
</template>

<script type="text/babel">
  import { hasClass } from '../utils/dom'

  export default {
    data () {
      return {
        classMap: {},
        colorMap: {},
        pointerAtLeftHalf: true,
        currentValue: this.value,
        hoverIndex: -1
      }
    },

    props: {
      value: {
        type: Number
      },
      field: {
        lowThreshold: {
          type: Number
        },
        highThreshold: {
          type: Number
        },
        max: {
          type: Number
        },
        colors: {
          type: Array
        },
        voidColor: {
          type: String
        },
        disabledVoidColor: {
          type: String
        },
        iconClasses: {
          type: Array
        },
        voidIconClass: {
          type: String
        },
        disabledVoidIconClass: {
          type: String
        },
        disabled: {
          type: Boolean
        },
        allowHalf: {
          type: Boolean
        },
        showText: {
          type: Boolean
        },
        textColor: {
          type: String
        },
        texts: {
          type: Array
        },
        textTemplate: {
          type: String
        }
      }
    },

    computed: {
      text () {
        let result = ''
        if (this.field.disabled) {
          result = this.field.textTemplate.replace(/\{\s*value\s*\}/, this.value)
        } else {
          result = this.field.texts[Math.ceil(this.currentValue) - 1]
        }
        return result
      },

      decimalStyle () {
        let width = ''
        if (this.field.disabled) {
          width = `${this.valueDecimal < 50 ? 0 : 50}%`
        }
        if (this.field.allowHalf) {
          width = '50%'
        }
        return {
          color: this.activeColor,
          width
        }
      },

      valueDecimal () {
        return this.value * 100 - Math.floor(this.value) * 100
      },

      decimalIconClass () {
        return this.getValueFromMap(this.value, this.classMap)
      },

      voidClass () {
        return this.field.disabled ? this.classMap.disabledVoidClass : this.classMap.voidClass
      },

      activeClass () {
        return this.getValueFromMap(this.currentValue, this.classMap)
      },

      activeColor () {
        return this.getValueFromMap(this.currentValue, this.colorMap)
      },

      classes () {
        let result = []
        let i = 0
        let threshold = this.currentValue
        if (this.field.allowHalf && this.currentValue !== Math.floor(this.currentValue)) {
          threshold--
        }
        for (; i < threshold; i++) {
          result.push(this.activeClass)
        }
        for (; i < this.field.max; i++) {
          result.push(this.voidClass)
        }
        return result
      }
    },

    watch: {
      value (val) {
        this.$emit('change', val)
        this.currentValue = val
        this.pointerAtLeftHalf = this.value !== Math.floor(this.value)
      }
    },

    methods: {
      getValueFromMap (value, map) {
        let result = ''
        if (value <= this.field.lowThreshold) {
          result = map.lowColor || map.lowClass
        } else if (value >= this.field.highThreshold) {
          result = map.highColor || map.highClass
        } else {
          result = map.mediumColor || map.mediumClass
        }
        return result
      },

      showDecimalIcon (item) {
        let showWhenDisabled = this.field.disabled && this.valueDecimal > 0 && item - 1 < this.value && item > this.value
        /* istanbul ignore next */
        let showWhenAllowHalf = this.field.allowHalf &&
          this.pointerAtLeftHalf &&
          item - 0.5 <= this.currentValue &&
          item > this.currentValue
        return showWhenDisabled || showWhenAllowHalf
      },

      getIconStyle (item) {
        const voidColor = this.field.disabled ? this.colorMap.disabledVoidColor : this.colorMap.voidColor
        return {
          color: item <= this.currentValue ? this.activeColor : voidColor
        }
      },

      selectValue (value) {
        if (this.field.disabled) {
          return
        }
        if (this.field.allowHalf && this.pointerAtLeftHalf) {
          this.$emit('input', this.currentValue)
        } else {
          this.$emit('input', value)
        }
      },

      setCurrentValue (value, event) {
        if (this.field.disabled) {
          return
        }
        /* istanbul ignore if */
        if (this.field.allowHalf) {
          let target = event.target
          if (hasClass(target, 'rate__item')) {
            target = target.querySelector('.rate__icon')
          }
          if (hasClass(target, 'rate__decimal')) {
            target = target.parentNode
          }
          this.pointerAtLeftHalf = event.offsetX * 2 <= target.clientWidth
          this.currentValue = this.pointerAtLeftHalf ? value - 0.5 : value
        } else {
          this.currentValue = value
        }
        this.hoverIndex = value
      },

      resetCurrentValue () {
        if (this.field.disabled) {
          return
        }
        if (this.field.allowHalf) {
          this.pointerAtLeftHalf = this.value !== Math.floor(this.value)
        }
        this.currentValue = this.value
        this.hoverIndex = -1
      }
    },

    created () {
      if (!this.value) {
//        this.$emit('input', 0)
      }
      this.classMap = {
        lowClass: this.field.iconClasses[0],
        mediumClass: this.field.iconClasses[1],
        highClass: this.field.iconClasses[2],
        voidClass: this.field.voidIconClass,
        disabledVoidClass: this.field.disabledVoidIconClass
      }
      this.colorMap = {
        lowColor: this.field.colors[0],
        mediumColor: this.field.colors[1],
        highColor: this.field.colors[2],
        voidColor: this.field.voidColor,
        disabledVoidColor: this.field.disabledVoidColor
      }
    }
  }
</script>

<style>
  .rate {
    height: 20px;
    line-height: 1;
  }

  .rate__icon, .rate__item {
    display: inline-block;
    position: relative;
  }

  .rate__item {
    font-size: 0px;
    vertical-align: middle;
  }

  .rate__icon {
    font-size: 35px;
    margin-right: 6px;
    color: rgb(191, 203, 217);
    transition: 0.3s;
  }

  .rate__icon.hover {
    transform: scale(1.5);
  }

  .rate__icon, .rate__item {
    display: inline-block;
    position: relative;
  }

  .rate__text {
    /*font-size: 14px;*/
    /*vertical-align: middle;*/
    /*position: relative;*/
    /*top: -8px;*/
  }

  [class*=" el-icon-"], [class^="el-icon-"] {
    speak: none;
    font-style: normal;
    font-weight: 400;
    text-transform: none;
    line-height: 1;
    vertical-align: baseline;
    display: inline-block;
    -webkit-font-smoothing: antialiased;
    font-family: element-icons;
  }

  .rate-icon-star-off::before {
    content: "";
  }

  .rate-icon-star-off::before {
    content: "";
  }


</style>
